package com.rxt.thermopro.ui.fragment

import android.content.ContentResolver
import android.graphics.Color
import android.graphics.DashPathEffect
import android.os.Bundle
import android.provider.Settings
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.app.common.base.BaseFragment
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.*
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.IFillFormatter
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
import com.github.mikephil.charting.utils.Utils
import com.rxt.thermopro.R
import com.rxt.thermopro.app.LocalDataDao
import com.rxt.thermopro.bean.ProbeHistoryBean
import com.rxt.thermopro.bean.TempBean
import com.rxt.thermopro.ui.chart.BBQMarkerView
import com.rxt.thermopro.ui.chart.HistoryMarkerView
import com.rxt.thermopro.viewmodel.BleMessageViewModel
import com.rxt.thermopro.viewmodel.BleMessageViewModel.Companion.DEVICE_TYPE_BBQ
import com.rxt.thermopro.viewmodel.BleMessageViewModel.Companion.DEVICE_TYPE_GRILL
import com.rxt.thermopro.viewmodel.BleMessageViewModel.Companion.DEVICE_TYPE_TP960
import com.rxt.thermopro.viewmodel.TempGraphPageViewModel
import kotlinx.android.synthetic.main.fragment_temp_graph_page.*
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.min

class TempGraphPageFragment : BaseFragment<TempGraphPageViewModel>() {
    override fun layoutId(): Int {
        return R.layout.fragment_temp_graph_page
    }

    companion object {

        private const val ARG_POSITION = "currentPosition"
        private const val ARG_DEVICE_TYPE = "deviceType"
        private const val ARG_ADDRESS = "address"

        fun newInstance(position: Int): TempGraphPageFragment {
            return TempGraphPageFragment().apply {
                arguments = Bundle().apply {
                    putInt(ARG_POSITION, position)
                }
            }
        }

        fun newInstance(position: Int, deviceType: Int, address: String): TempGraphPageFragment {
            return TempGraphPageFragment().apply {
                arguments = Bundle().apply {
                    putInt(ARG_POSITION, position)
                    putInt(ARG_DEVICE_TYPE, deviceType)
                    putString(ARG_ADDRESS, address)
                }
            }
        }
    }

    private lateinit var mBleViewModel: BleMessageViewModel
    private var currentPosition = -1
    private var mDeviceType = -1
    private var mAddress = ""
    val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm")
    val dateFormat2 = SimpleDateFormat("yyyy-MM-dd-HH-mm")
    private val dateFormat1 = SimpleDateFormat("dd-MM-yyyy hh:mm")
    private var highLimitLine = -1f
    private var lowLimitLine = -1f
    private var cacheHistoryTemp = mutableListOf<TempBean>()

    override fun initView(savedInstanceState: Bundle?) {
        currentPosition = arguments?.getInt(ARG_POSITION, -1) ?: -1
        mDeviceType = arguments?.getInt(ARG_DEVICE_TYPE, -1) ?: -1
        mAddress = arguments?.getString(ARG_ADDRESS, "") ?: ""
        mBleViewModel =
            ViewModelProvider(requireActivity()).get(BleMessageViewModel::class.java)

        mBleViewModel.notifyMsgData.observeInFragment(this, Observer { item->
            val it=item.values.last()
            if (it.last().address == mAddress) {
                when (mDeviceType) {
                    DEVICE_TYPE_BBQ, DEVICE_TYPE_GRILL -> {
//                        mBleViewModel.refreshTemp()
                    }
                    DEVICE_TYPE_TP960 -> {
                        if (cacheHistoryTemp.isNotEmpty() &&
                            it.last().temperatureNUm != cacheHistoryTemp.last().tempNum1
                        ) {
//                            mViewModel.getHistoryTemp(mAddress, currentPosition)
                        }
                    }
                }
            }
        })

        when (mDeviceType) {
            DEVICE_TYPE_BBQ, DEVICE_TYPE_GRILL -> {
                mBleViewModel.notifyHistoryTempData.observeInFragment(this, Observer {
                    val keyStr = "${mAddress}_${currentPosition}"
                    if (it.containsKey(keyStr)) {
                        if (LocalDataDao.INSTANCE.getTempUnit() == LocalDataDao.TEMP_UNIT_F) {
                            var minTempNum = 0f
                            var maxTempNum = 0f
                            val newList = mutableListOf<ProbeHistoryBean>()
                            for (i in 0 until it[keyStr]!!.size) {
                                val oldBean = it[keyStr]!![i]
                                val newBean = ProbeHistoryBean(
                                    oldBean.probeIndex, oldBean.address,
                                    LocalDataDao.INSTANCE.transUnitCToF(oldBean.tempNum),
                                    oldBean.tempTime, oldBean.profile, oldBean.historyIndex
                                )
                                newBean.tempTime.toFloatOrNull()?.let { item ->
                                    if (item < minTempNum) {
                                        minTempNum = item
                                    }
                                }
                                newBean.tempNum.toFloatOrNull()?.let { item ->
                                    if (item > maxTempNum) {
                                        maxTempNum = item
                                    }
                                }
                                newList.add(newBean)
                            }
                            if (minTempNum<0){
                                minTempNum -= 5
                            }
                            setChart(chartView, newList, minTempNum, maxTempNum)
                        } else {
                            var minTempNum = 0f
                            var maxTempNum = 0f
                            for (i in 0 until it[keyStr]!!.size) {
                                it[keyStr]!![i].tempTime.toFloatOrNull()?.let { item ->
                                    if (item < minTempNum) {
                                        minTempNum = item
                                    }
                                }
                                it[keyStr]!![i].tempNum.toFloatOrNull()?.let { item ->
                                    if (item > maxTempNum) {
                                        maxTempNum = item
                                    }
                                }
                            }
                            if (minTempNum<0){
                                minTempNum -= 5
                            }
                            setChart(
                                chartView, it[keyStr] ?: mutableListOf(),
                                minTempNum, maxTempNum
                            )
                        }
                    }
                })
            }
            DEVICE_TYPE_TP960 -> {
//                mBleViewModel.notifyHistoryTempTP960Data.observeInFragment(this, Observer { item ->
//                    item[0]?.let {
//                        println("======> notifyHistoryTempTP960Data=$it")
//                        if (LocalDataDao.INSTANCE.getTempUnit() == LocalDataDao.TEMP_UNIT_F) {
//                            val newList = mutableListOf<TempBean>()
//                            for (i in 0 until it.size) {
//                                val newBean = TempBean()
//                                newBean.tempNum1 =
//                                    LocalDataDao.INSTANCE.transUnitCToF(it[i].tempNum1)
//                                newBean.tempTime = it[i].tempTime
//                                newList.add(newBean)
//                            }
//                            setChart(chartView, newList)
//                            cacheHistoryTemp.clear()
//                            cacheHistoryTemp.addAll(newList)
//                        } else {
//                            setChart(chartView, it)
//                            cacheHistoryTemp.clear()
//                            cacheHistoryTemp.addAll(it)
//                        }
//                    }
//                })
                mBleViewModel.notifyHistoryTempData.observeInFragment(this, Observer {
                    val keyStr = "${mAddress}_${currentPosition}"
                    println("123->  notifyHistoryTempData=${it[keyStr]!!.last().tempNum}")
                    if (it.containsKey(keyStr)) {
                        if (LocalDataDao.INSTANCE.getTempUnit() == LocalDataDao.TEMP_UNIT_F) {
                            var minTempNum = 0f
                            var maxTempNum = 0f
                            val newList = mutableListOf<ProbeHistoryBean>()
                            for (i in 0 until it[keyStr]!!.size) {
                                val oldBean = it[keyStr]!![i]
                                val newBean = ProbeHistoryBean(
                                    oldBean.probeIndex, oldBean.address,
                                    LocalDataDao.INSTANCE.transUnitCToF(oldBean.tempNum),
                                    oldBean.tempTime, oldBean.profile, oldBean.historyIndex
                                )
                                newBean.tempNum.toFloatOrNull()?.let { item ->
                                    if (item < minTempNum) {
                                        minTempNum = item
                                    }
                                }
                                newBean.tempNum.toFloatOrNull()?.let { item ->
                                    if (item > maxTempNum) {
                                        maxTempNum = item
                                    }
                                }
                                newList.add(newBean)
                            }
                            if (minTempNum<0){
                                minTempNum -= 5
                            }
                            setChart(chartView, newList, minTempNum, maxTempNum)
                        } else {
                            var minTempNum = 0f
                            var maxTempNum = 0f
                            for (i in 0 until it[keyStr]!!.size) {
                                it[keyStr]!![i].tempNum.toFloatOrNull()?.let { item ->
                                    if (item < minTempNum) {
                                        minTempNum = item
                                    }
                                }
                                it[keyStr]!![i].tempNum.toFloatOrNull()?.let { item ->
                                    if (item > maxTempNum) {
                                        maxTempNum = item
                                    }
                                }
                            }
                            if (minTempNum<0){
                                minTempNum -= 5
                            }
                            setChart(
                                chartView, it[keyStr] ?: mutableListOf(),
                                minTempNum, maxTempNum
                            )
                        }
                    }
                })
            }
            else -> setChart(chartView, mutableListOf(), 0f, 100f)
        }

        mViewModel.profileData.observe(this, Observer {
            if (it.highTemperatureNum.isEmpty() && it.lowTemperatureNum.isEmpty() && !it.singleTemp) {
                highLimitLine = -1f
                lowLimitLine = -1f
            } else if (it.singleTemp) {
                highLimitLine = LocalDataDao.INSTANCE.formatHighValueUnitNum(it).toFloat()
            } else {
                highLimitLine = LocalDataDao.INSTANCE.formatHighValueUnitNum(it).toFloat()
                lowLimitLine = LocalDataDao.INSTANCE.formatLowValueUntNum(it).toFloat()
            }
            when (mDeviceType) {
                DEVICE_TYPE_BBQ, DEVICE_TYPE_GRILL -> {
                    mBleViewModel.getTempHistoryByCache(mAddress, currentPosition)
                }

                DEVICE_TYPE_TP960 -> {
                    mBleViewModel.getTempHistoryByCache(mAddress, currentPosition)
                }
            }
        })
        mViewModel.getProfile(currentPosition, mAddress)

    }

    private fun setChart(
        mChart: LineChart, list: MutableList<ProbeHistoryBean>,
        minTempNum: Float, maxTempNum: Float
    ) {
        val cv: ContentResolver = requireActivity().contentResolver
        val strTimeFormat = Settings.System.getString(
            cv,
            Settings.System.TIME_12_24
        )
        var is24 = true
        var currentDateFormat = if (strTimeFormat == "24") {
            is24 = true
            dateFormat
        } else {
            is24 = false
            dateFormat1
        }
        mChart.apply {
            // background color
            setBackgroundColor(Color.WHITE)
            // disable description text
            description.isEnabled = false
            // enable touch gestures
            setTouchEnabled(true)
            // create marker to display box when values are selected
            val mv = HistoryMarkerView(requireContext(), R.layout.custom_marker_view_1,
                list,is24)
            // Set the marker to the chart
            mv.chartView = this
            marker = mv
            setDrawGridBackground(false)

            // enable scaling and dragging
            isDragEnabled = true
            setScaleEnabled(false)
            // force pinch zoom along both axis
            setPinchZoom(true)
            legend.isEnabled = false
            setDrawBorders(false)
        }

        var xAxis: XAxis = mChart.xAxis
        // // X-Axis Style // //
        xAxis = mChart.xAxis
        xAxis.setDrawAxisLine(true)
        xAxis.position = XAxis.XAxisPosition.BOTTOM
        xAxis.granularity = 1f;
        // vertical grid lines
        xAxis.setDrawGridLines(false)
//        xAxis.enableGridDashedLine(10f, 10f, 0f)
        xAxis.setLabelCount(5, true)
        if (list.size < 4) {
            xAxis.axisMaximum = 4f
        } else {
            xAxis.axisMaximum = list.size.toFloat()
        }
        xAxis.axisMinimum = 0f
        xAxis.setValueFormatter { value, _ ->
//            println("============>setValueFormatter value=$value")
            var str = ""
            when {
                list.isEmpty() -> {
//                    val date = Date()
//                    date.time = (System.currentTimeMillis() + 60L * 1000 * value).toLong()
//                    val timeStr = currentDateFormat.format(date)
//                    val strTrip = getAMOrPM(date,is24)
//                    str = timeStr.split(" ")[1]+strTrip
                    str=LocalDataDao.INSTANCE.formatTimeAMPM(
                        (System.currentTimeMillis() + 60L * 1000 * value).toLong(),is24)
                }
                list.size < 4 -> {
                    val listSize = list.size
                    val tempTime =
                        if (value.toInt() >= listSize) (list.last().tempTime.toLong() + (value - listSize + 1).toLong() * 60L * 1000L).toString()
                        else list[value.toInt()].tempTime
//                    val date = Date()
//                    date.time = tempTime.toLong()
//                    val timeStr = currentDateFormat.format(date)
//                    val strTrip = getAMOrPM(date,is24)
//                    str = timeStr.split(" ")[1]+strTrip
                    str=LocalDataDao.INSTANCE.formatTimeAMPM( tempTime.toLong(),is24)
                }
                else -> {
                    val listSize = list.size
                    val tempTime =
                        if (value.toInt() >= listSize) (list.last().tempTime.toLong() + (value - listSize + 1).toLong() * 60L * 1000L).toString()
                        else list[value.toInt()].tempTime
//                    val date = Date()
//                    date.time = tempTime.toLong()
//                    val timeStr = currentDateFormat.format(date)
//                    val strTrip = getAMOrPM(date,is24)
//                    str = timeStr.split(" ")[1]+strTrip
                    str=LocalDataDao.INSTANCE.formatTimeAMPM( tempTime.toLong(),is24)
                }
            }
//            println("============>setValueFormatter=$str  timeStr=$timeStr value=$value")
            str
        }

        // // Y-Axis Style // //
        val yAxis: YAxis = mChart.axisLeft

        // disable dual axis (only use LEFT axis)
        mChart.axisRight.isEnabled = false

        // horizontal grid lines
        yAxis.setDrawGridLines(false)
//        yAxis.enableGridDashedLine(10f, 10f, 0f)

        // axis range
//        if (highLimitLine != -1f) {
//            val a = highLimitLine % 3
//            val b = highLimitLine / 3
//            val newHighLimit = b * 4
//            yAxis.axisMaximum = newHighLimit
//        } else {
//            val a = 100f % 3
//            val b = 100f / 3
//            val newHighLimit = b * 4
//            yAxis.axisMaximum = newHighLimit
//        }
        if (maxTempNum != 0f) {
            val newMax = if (maxTempNum < highLimitLine) {
                highLimitLine
            } else {
                maxTempNum
            }
            val a = newMax % 3
            val b = newMax / 3
            val c = b % 5
            val newHighLimit = (b+5-c) * 4
            yAxis.axisMaximum = newHighLimit
        } else {
            val newMax = if (LocalDataDao.INSTANCE
                    .convertUnitNum("100").toFloat() < highLimitLine
            ) {
                highLimitLine
            } else {
                LocalDataDao.INSTANCE.convertUnitNum("100").toFloat()
            }
            val a = newMax % 3
            val b = newMax / 3
            val c = b % 5
            val newHighLimit = (b+5-c) * 4
            yAxis.axisMaximum = newHighLimit
        }
        yAxis.axisMinimum = minTempNum
        yAxis.setLabelCount(5, true)
        yAxis.setDrawZeroLine(false)

        // draw limit lines behind data instead of on top
        yAxis.setDrawLimitLinesBehindData(true)
        xAxis.setDrawLimitLinesBehindData(true)

        val ll1 = LimitLine(highLimitLine, "${highLimitLine.toInt()}°")
        ll1.lineWidth = 1f
        ll1.enableDashedLine(10f, 10f, 0f)
        ll1.labelPosition = LimitLine.LimitLabelPosition.RIGHT_TOP
        ll1.textColor = resources.getColor(android.R.color.holo_red_light)
        ll1.textSize = 10f
//        ll1.typeface = tfRegular

        val ll2 = LimitLine(lowLimitLine, "${lowLimitLine.toInt()}°")
        ll2.lineWidth = 1f
        ll2.enableDashedLine(10f, 10f, 0f)
        ll2.labelPosition = LimitLine.LimitLabelPosition.RIGHT_BOTTOM
        ll2.textSize = 10f
//        ll2.typeface = tfRegular
        yAxis.removeAllLimitLines()
        // add limit lines
        if (highLimitLine != -1f) {
            yAxis.addLimitLine(ll1)
        }
        if (lowLimitLine != -1f) {
            yAxis.addLimitLine(ll2)
        }

        // add data
        if (list.isNotEmpty()) {
            setData(list, mChart)
        }
        // draw points over time
        mChart.animateX(800)
        // get the legend (only possible after setting data)
        val l = mChart.legend
        // draw legend entries as lines
        l.form = Legend.LegendForm.LINE
    }


    private fun setData(list: MutableList<ProbeHistoryBean>, mChart: LineChart) {
        val values = ArrayList<Entry>()
        for (i in 0 until list.size) {
            val tempNum = list[i].tempNum.toFloat()
            values.add(
                Entry(
                    i.toFloat(),
                    tempNum,
                    resources.getDrawable(R.mipmap.add_device_redpoint)
                )
            )
        }

        val set1: LineDataSet
        if (mChart.data != null &&
            mChart.data.dataSetCount > 0
        ) {
            set1 = mChart.data.getDataSetByIndex(0) as LineDataSet
            set1.values = values
            set1.notifyDataSetChanged()
            mChart.data.notifyDataChanged()
            mChart.notifyDataSetChanged()
        } else {
            // create a dataset and give it a type
            set1 = LineDataSet(values, "DataSet 1")
            set1.setDrawIcons(false)

            // draw dashed line
//            set1.enableDashedLine(10f, 5f, 0f)
            set1.disableDashedLine()
            set1.mode = LineDataSet.Mode.LINEAR_DISCONNECT_ZERO

            // black lines and points
            set1.color = Color.parseColor("#458B74")
            set1.setCircleColor(Color.RED)

            // line thickness and point size
            set1.lineWidth = 1f
            set1.circleRadius = 3f

            // draw points as solid circles
            set1.setDrawCircleHole(true)
            set1.circleHoleColor = Color.WHITE

            // customize legend entry
            set1.formLineWidth = 1f
            set1.formLineDashEffect = DashPathEffect(floatArrayOf(10f, 5f), 0f)
            set1.formSize = 15f

            // text size of values
            set1.valueTextSize = 9f

            // draw selection line as dashed
            set1.enableDashedHighlightLine(10f, 5f, 0f)
            set1.setDrawHighlightIndicators(true)
            set1.setDrawHorizontalHighlightIndicator(false)
            set1.highlightLineWidth = 1F
            set1.highLightColor = resources.getColor(android.R.color.holo_blue_light)
            set1.setDrawValues(false)
            set1.setDrawCircles(false)
            set1.isDrawMaxMinValuesAndCircle = false

            // set the filled area
            set1.setDrawFilled(false)
            set1.fillFormatter =
                IFillFormatter { dataSet, dataProvider -> mChart.axisLeft.axisMinimum }

            // set color of filled area
            if (Utils.getSDKInt() >= 18) {
                // drawables only supported on api level 18 and above
                val drawable = ContextCompat.getDrawable(requireContext(), R.drawable.fade_blue)
                set1.fillDrawable = drawable
            } else {
                set1.fillColor = Color.BLACK
            }
            val dataSets = ArrayList<ILineDataSet>()
            dataSets.add(set1) // add the data sets

            // create a data object with the data sets
            val data = LineData(dataSets)

            // set data
            mChart.data = data
        }
    }
}